func resourceBillingBudgetResourceV0() *schema.Resource {
	return &schema.Resource{
		Schema: map[string]*schema.Schema{
			"amount": {
				Type:        schema.TypeList,
				Required:    true,
				Description: `The budgeted amount for each usage period.`,
				MaxItems:    1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"last_period_amount": {
							Type:     schema.TypeBool,
							Optional: true,
							Description: `Configures a budget amount that is automatically set to 100% of
last period's spend.
Boolean. Set value to true to use. Do not set to false, instead
use the 'specified_amount' block.`,
							ExactlyOneOf: []string{"amount.0.specified_amount", "amount.0.last_period_amount"},
						},
						"specified_amount": {
							Type:     schema.TypeList,
							Optional: true,
							Description: `A specified amount to use as the budget. currencyCode is
optional. If specified, it must match the currency of the
billing account. The currencyCode is provided on output.`,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"currency_code": {
										Type:        schema.TypeString,
										Computed:    true,
										Optional:    true,
										Description: `The 3-letter currency code defined in ISO 4217.`,
									},
									"nanos": {
										Type:     schema.TypeInt,
										Optional: true,
										Description: `Number of nano (10^-9) units of the amount.
The value must be between -999,999,999 and +999,999,999
inclusive. If units is positive, nanos must be positive or
zero. If units is zero, nanos can be positive, zero, or
negative. If units is negative, nanos must be negative or
zero. For example $-1.75 is represented as units=-1 and
nanos=-750,000,000.`,
									},
									"units": {
										Type:     schema.TypeString,
										Optional: true,
										Description: `The whole units of the amount. For example if currencyCode
is "USD", then 1 unit is one US dollar.`,
									},
								},
							},
							ExactlyOneOf: []string{"amount.0.specified_amount", "amount.0.last_period_amount"},
						},
					},
				},
			},
			"billing_account": {
				Type:        schema.TypeString,
				Required:    true,
				ForceNew:    true,
				Description: `ID of the billing account to set a budget on.`,
			},
			"threshold_rules": {
				Type:     schema.TypeList,
				Required: true,
				Description: `Rules that trigger alerts (notifications of thresholds being
crossed) when spend exceeds the specified percentages of the
budget.`,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"threshold_percent": {
							Type:     schema.TypeFloat,
							Required: true,
							Description: `Send an alert when this threshold is exceeded. This is a
1.0-based percentage, so 0.5 = 50%. Must be >= 0.`,
						},
						"spend_basis": {
							Type:         schema.TypeString,
							Optional:     true,
							ValidateFunc: validation.StringInSlice([]string{"CURRENT_SPEND", "FORECASTED_SPEND", ""}, false),
							Description: `The type of basis used to determine if spend has passed
the threshold. Default value: "CURRENT_SPEND" Possible values: ["CURRENT_SPEND", "FORECASTED_SPEND"]`,
							Default: "CURRENT_SPEND",
						},
					},
				},
			},
			"all_updates_rule": {
				Type:     schema.TypeList,
				Optional: true,
				Description: `Defines notifications that are sent on every update to the
billing account's spend, regardless of the thresholds defined
using threshold rules.`,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"disable_default_iam_recipients": {
							Type:     schema.TypeBool,
							Optional: true,
							Description: `Boolean. When set to true, disables default notifications sent
when a threshold is exceeded. Default recipients are
those with Billing Account Administrators and Billing
Account Users IAM roles for the target account.`,
							Default: false,
						},
						"monitoring_notification_channels": {
							Type:     schema.TypeList,
							Optional: true,
							Description: `The full resource name of a monitoring notification
channel in the form
projects/{project_id}/notificationChannels/{channel_id}.
A maximum of 5 channels are allowed.`,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
							AtLeastOneOf: []string{"all_updates_rule.0.pubsub_topic", "all_updates_rule.0.monitoring_notification_channels"},
						},
						"pubsub_topic": {
							Type:     schema.TypeString,
							Optional: true,
							Description: `The name of the Cloud Pub/Sub topic where budget related
messages will be published, in the form
projects/{project_id}/topics/{topic_id}. Updates are sent
at regular intervals to the topic.`,
							AtLeastOneOf: []string{"all_updates_rule.0.pubsub_topic", "all_updates_rule.0.monitoring_notification_channels"},
						},
						"schema_version": {
							Type:     schema.TypeString,
							Optional: true,
							Description: `The schema version of the notification. Only "1.0" is
accepted. It represents the JSON schema as defined in
https://cloud.google.com/billing/docs/how-to/budgets#notification_format.`,
							Default: "1.0",
						},
					},
				},
			},
			"budget_filter": {
				Type:     schema.TypeList,
				Computed: true,
				Optional: true,
				Description: `Filters that define which resources are used to compute the actual
spend against the budget.`,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"credit_types": {
							Type:     schema.TypeList,
							Computed: true,
							Optional: true,
							Description: `A set of subaccounts of the form billingAccounts/{account_id},
specifying that usage from only this set of subaccounts should
be included in the budget. If a subaccount is set to the name of
the parent account, usage from the parent account will be included.
If the field is omitted, the report will include usage from the parent
account and all subaccounts, if they exist.`,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
						"credit_types_treatment": {
							Type:         schema.TypeString,
							Optional:     true,
							ValidateFunc: validation.StringInSlice([]string{"INCLUDE_ALL_CREDITS", "EXCLUDE_ALL_CREDITS", "INCLUDE_SPECIFIED_CREDITS", ""}, false),
							Description: `Specifies how credits should be treated when determining spend
for threshold calculations. Default value: "INCLUDE_ALL_CREDITS" Possible values: ["INCLUDE_ALL_CREDITS", "EXCLUDE_ALL_CREDITS", "INCLUDE_SPECIFIED_CREDITS"]`,
							Default:      "INCLUDE_ALL_CREDITS",
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
						"labels": {
							Type:     schema.TypeMap,
							Computed: true,
							Optional: true,
							Description: `A single label and value pair specifying that usage from only
this set of labeled resources should be included in the budget.`,
							Elem:         &schema.Schema{Type: schema.TypeString},
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
						"projects": {
							Type:     schema.TypeList,
							Optional: true,
							Description: `A set of projects of the form projects/{project_number},
specifying that usage from only this set of projects should be
included in the budget. If omitted, the report will include
all usage for the billing account, regardless of which project
the usage occurred on.`,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
						"services": {
							Type:     schema.TypeList,
							Computed: true,
							Optional: true,
							Description: `A set of services of the form services/{service_id},
specifying that usage from only this set of services should be
included in the budget. If omitted, the report will include
usage for all the services. The service names are available
through the Catalog API:
https://cloud.google.com/billing/v1/how-tos/catalog-api.`,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
						"subaccounts": {
							Type:     schema.TypeList,
							Computed: true,
							Optional: true,
							Description: `A set of subaccounts of the form billingAccounts/{account_id},
specifying that usage from only this set of subaccounts should
be included in the budget. If a subaccount is set to the name of
the parent account, usage from the parent account will be included.
If the field is omitted, the report will include usage from the parent
account and all subaccounts, if they exist.`,
							Elem: &schema.Schema{
								Type: schema.TypeString,
							},
							AtLeastOneOf: []string{"budget_filter.0.projects", "budget_filter.0.credit_types_treatment", "budget_filter.0.services", "budget_filter.0.subaccounts", "budget_filter.0.labels"},
						},
					},
				},
			},
			"display_name": {
				Type:        schema.TypeString,
				Optional:    true,
				Description: `User data for display name in UI. Must be <= 60 chars.`,
			},
			"name": {
				Type:     schema.TypeString,
				Computed: true,
				Description: `Resource name of the budget. The resource name
implies the scope of a budget. Values are of the form
billingAccounts/{billingAccountId}/budgets/{budgetId}.`,
			},
		},
	}
}

func resourceBillingBudgetUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
	log.Printf("[DEBUG] Attributes before migration: %#v", rawState)

	rawState["name"] = GetResourceNameFromSelfLink(rawState["name"].(string))

	log.Printf("[DEBUG] Attributes after migration: %#v", rawState)
	return rawState, nil
}
